﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;


namespace Hypermarket_Serial_Port
{
    class CommuncationManager
    {
        //private SendDataManager mSDManager;
        //private ReceiveDataManager mRDManager;
        private SerialPort mySerialPort = new SerialPort();

        private static CommuncationManager mInstance;
        private CommuncationManager(string PortName) 
        {
            try
            {
                //mRDManager = ReceiveDataManager.getInstance();
                //mSDManager = SendDataManager.getInstance();
                InitSerialPort(PortName);
            }
            catch
            {
                throw;
            }
        }

        private void InitSerialPort(string PortName)
        {
            mySerialPort.BaudRate = 9600;
            mySerialPort.Parity = Parity.None;
            mySerialPort.StopBits = StopBits.Two;
            mySerialPort.DataBits = 8;
            mySerialPort.Handshake = Handshake.None;
            mySerialPort.WriteTimeout = 80;
            mySerialPort.ReadTimeout = 80;
            mySerialPort.PortName = PortName;
            try
            {
                if (!mySerialPort.IsOpen)
                    mySerialPort.Open();
            }
            catch
            {
                throw;
            }
        }

        public static CommuncationManager getInstance(string PortName)
        {
            if (mInstance == null)
            {
                mInstance = new CommuncationManager(PortName);
            }
            return mInstance;
        }

        public bool SerialPortSend(byte[] data)
        {
            try
            {
                mySerialPort.Write(data, 0, data.Length);
                Console.WriteLine("Data Send: {0}", ByteArrayToHexString(data));
                SerialPortLog.Log("Data Send: ");
                SerialPortLog.Log(ByteArrayToHexString(data));
            //    System.Threading.Thread.Sleep(40);
                return true;
            }
            catch (System.IO.IOException e)
            {
                SerialPortLog.Log(e.Message);
                return false;
            }
            catch (TimeoutException)
            {
                Console.WriteLine("Serial Port Read Write Out!\n");
                return false;
            }
        }

        public bool SerialPortReceive(out byte[] data)
        {
            data = new byte[] { };
            try
            {
                System.Threading.Thread.Sleep(80);
                // Obtain the number of bytes waiting in the port's buffer
                int bytes = mySerialPort.BytesToRead;

                // Create a byte array buffer to hold the incoming data
                data = new byte[bytes];

                // Read the data from the port and store it in our buffer
                mySerialPort.Read(data, 0, bytes);
                if (data.Count() != 0)
                {
                    Console.Write("Data Received: ");
                    Console.WriteLine(ByteArrayToHexString(data));
                    SerialPortLog.Log("Data Received: ");
                    SerialPortLog.Log(ByteArrayToHexString(data));
                    return true;
                }
                else
                {
                    Console.WriteLine("Serial Port Read Time Out!\n");
                    SerialPortLog.Log("Serial Port Read No Data!\n");
                    return false;
                }
            }
            catch (System.IO.IOException e)
            {
                SerialPortLog.Log("Serial Port IO Error!\n");
                return false;
            }
            catch (TimeoutException)
            {
                Console.WriteLine("Serial Port Read Time Out!\n");
                SerialPortLog.Log("Serial Port Read Time Out!\n");
                return false;
            }
        }

        //private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        //{
        //    int bytes = mySerialPort.BytesToRead;

        //     Create a byte array buffer to hold the incoming data
        //    byte[] data = new byte[bytes];

        //     Read the data from the port and store it in our buffer
        //    mySerialPort.Read(data, 0, bytes);
        //    Console.Write("Data Received: ");
        //    Console.WriteLine(ByteArrayToHexString(data));
        //}

        private string ByteArrayToHexString(byte[] data)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            try
            {
                foreach (byte b in data)
                {
                    sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
                }
                return sb.ToString().ToUpper();
            }
            catch
            {
                return sb.ToString().ToUpper();
            }
        }

        private static byte[] HexStringToByteArray(string s)
        {
            byte[] buffer = new byte[] { };
            try
            {
                s = s.Replace(" ", "");
                buffer = new byte[s.Length / 2];
                for (int i = 0; i < s.Length; i += 2)
                {
                    buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
                }
                return buffer;
            }
            catch
            {
                return buffer;
            }
        }
    }
}
